﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.IO.Compression;
using System.IO;
using System.Threading;
using System.Security.Cryptography;
using System.Xml;
using RAP.Framework.Libary.JSON.Conversion;
using System.Web;
using System.Threading.Tasks;

namespace RAP.Framework.Libary.Utils
{
  /// <summary>
  /// String字符串扩展
  /// </summary>
  public static partial class Extensions
  {
    #region 字符串扩展

    /// <summary>
    /// 对指定的Url字符串进行编码
    /// </summary>
    /// <param name="url"></param>
    /// <param name="defaultValue">默认值</param>
    /// <returns></returns>
    public static string UrlEncode(this string url, string defaultValue = null)
    {
      if (url.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return HttpUtility.UrlEncode(url);
    }

    /// <summary>
    /// 对指定的Url字符串进行解码
    /// </summary>
    /// <param name="url"></param>
    /// <param name="defaultValue">默认值</param>
    /// <returns></returns>
    public static string UrlDecode(this string url, string defaultValue = null)
    {
      if (url.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return HttpUtility.UrlDecode(url);
    }

    /// <summary>
    /// 判断当前字符串是否等于被比较的字符串中的任意一个，被比较字符串以逗号“,”分割
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="compares"></param>
    /// <returns></returns>
    public static bool IsEqualsAny(this string exp, string compares)
    {
      return exp.IsEqualsAny(compares.Split(','));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="compares"></param>
    /// <returns></returns>
    public static bool IsEqualsAny(this string exp, params string[] compares)
    {
      if (exp.IsNullOrEmpty() || compares.IsNullOrEmpty())
      {
        return false;
      }
      foreach (string compare in compares)
      {
        if (exp.Equals(compare))
        {
          return true;
        }
      }
      return false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="finds"></param>
    /// <returns></returns>
    public static int IndexOfAny(this string exp, params string[] finds)
    {
      foreach (var find in finds)
      {
        var idx = exp.IndexOf(find);
        if (idx >= 0) return idx;
      }
      return -1;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="finds"></param>
    /// <returns></returns>
    public static bool StartsWithAny(this string exp, params string[] finds)
    {
      foreach (var find in finds)
      {
        if (exp.StartsWith(find)) return true;
      }
      return false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="finds"></param>
    /// <returns></returns>
    public static bool EndsWithAny(this string exp, params string[] finds)
    {
      foreach (var find in finds)
      {
        if (exp.EndsWith(find)) return true;
      }
      return false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="spliter"></param>
    /// <returns></returns>
    public static string[] Split(this string exp, params string[] spliter)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      return exp.Split(spliter, StringSplitOptions.RemoveEmptyEntries);
    }

    /// <summary>
    /// 将当前字符串作为类型名称并实例化一个对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="typeName"></param>
    /// <returns></returns>
    public static T CreateInstance<T>(this string typeName)
    {
      Type type = Type.GetType(typeName);
      if (type == null)
      {
        return default(T);
      }
      return type.CreateInstance<T>();
    }

    /// <summary>
    /// 向StringBuilder的添加一个具有参数数组的Append方法
    /// </summary>
    /// <param name="sb"></param>
    /// <param name="param"></param>
    /// <returns></returns>
    public static StringBuilder Append(this StringBuilder sb, params object[] param)
    {
      if (param != null)
      {
        foreach (object obj in param)
        {
          sb.Append(obj);
        }
      }
      return sb;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="arguments"></param>
    /// <returns></returns>
    public static string format(this string exp, params object[] arguments)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      return string.Format(exp, arguments);
    }

    /// <summary>
    /// 将指定字符串按换行符分割后进行缩进再拼接
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="indent"></param>
    /// <returns></returns>
    public static string Indent(this string exp, int indent = 1)
    {
      return exp.Split('\n').Join("	".Copy(indent));
    }

    private static Regex _trimSpace = new Regex(" {2,}", RegexOptions.Compiled | RegexOptions.Multiline);

    /// <summary>
    /// 取消字符串中连续2个以上的空格
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string TrimSpace(this string exp)
    {
      return _trimSpace.Replace(exp, " ");
    }

    /// <summary>
    /// 将指定字符串转换成Regex对象
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static Regex ToRegex(this string exp
      , RegexOptions options = RegexOptions.Compiled | RegexOptions.Compiled | RegexOptions.IgnoreCase
      , Regex defaultValue = null)
    {
      if (exp.IsNullOrEmpty())
      {
        return defaultValue;
      }
      return new Regex(exp, options);
    }

    /// <summary>
    /// 扩展字符串的ToEnumValue方法
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static T ToEnumValue<T>(this string exp, T defaultValue = default(T))
    {
      if (string.IsNullOrEmpty(exp))
      {
        return defaultValue;
      }
      Type type = typeof(T);
      object enumValue = null;
      string[] valueArr = exp.Split(',', ' ', '/', '|');

      foreach (string str in valueArr)
      {
        if (string.IsNullOrEmpty(str.Trim()))
        {
          continue;
        }
        if (enumValue == null)
        {
          enumValue = Enum.Parse(type, str);
        }
        else
        {
          enumValue = (int)enumValue | (int)Enum.Parse(type, str);
        }
      }

      return (T)((object)enumValue);
    }

    /// <summary>
    /// 获取指定枚举值的名称
    /// </summary>
    /// <param name="value"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string GetNames(this Enum value, string defaultValue = null)
    {
      Type type = value.GetType();

      Array values = Enum.GetValues(type);
      List<String> names = new List<string>();

      foreach (object v in values)
      {
        if (value.Equals(v))
        {
          names.Add(Enum.GetName(type, v));
        }
      }
      string result = names.Join(",");
      if (string.IsNullOrEmpty(result))
      {
        result = defaultValue;
      }
      return result;
    }

    /// <summary>
    /// 检测指定字符串是否以小写开头
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static bool IsStartWithLowerCase(this string exp)
    {
      if (string.IsNullOrEmpty(exp))
      {
        return false;
      }
      char firstChar = exp[0];
      return firstChar > 97;
    }

    /// <summary>
    /// 将首字母转换成小写
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string ToFirstCharLowerCaseString(this string exp)
    {
      if (string.IsNullOrEmpty(exp))
      {
        return null;
      }
      string firstChar = exp[0].ToString().ToLower();
      return firstChar + exp.Substring(1);
    }

    /// <summary>
    /// 重复指定字符串指定次数
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public static string Repeat(this string exp, int count)
    {
      if (count <= 0)
      {
        return string.Empty;
      }
      string[] arr = new string[count];
      for (int i = 0; i < count; i++)
      {
        arr[i] = exp;
      }
      return string.Join("", arr);
    }

    /// <summary>
    /// 给指定的url地址增加版本号
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static string AddUrlVersion(this string url, string version)
    {
      string tag = "?";
      if (url.IndexOf('?') > 0)
      {
        tag = "&";
      }
      url = url + tag + "v=" + version;
      return url;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static object Eval(this string exp)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      exp = exp.Trim();
      return JsonConvert.Import(exp);
    }

    /// <summary>
    /// 复制指定字符串指定数量，并以separator作为分割字符
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="count"></param>
    /// <param name="separator"></param>
    /// <returns></returns>
    public static string Copy(this string exp, int count, string separator = "")
    {
      List<String> result = new List<string>();
      for (int i = 0; i < count; i++)
      {
        result.Add(exp);
      }
      return String.Join(separator, result.ToArray());
    }

    /// <summary>
    /// 将指定路径的文件内容
    /// </summary>
    /// <param name="file"></param>
    /// <param name="exclusive">是否文件独占式访问</param>
    /// <returns></returns>
    public static string ReadAllText(this string file, bool exclusive = false)
    {
      if (File.Exists(file))
      {
        if (exclusive)
        {
          using (FileStream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
          {
            return stream.ReadAllText();
          }
        }
        else
        {
          return File.ReadAllText(file);
        }
      }
      else
      {
        throw new FileNotFoundException("JSON文件不存在：" + file);
      }
    }

    /// <summary>
    /// 异步读取指定文件的所有文本内容
    /// </summary>
    /// <param name="file"></param>
    /// <param name="exclusive">是否文件独占式访问</param>
    /// <returns></returns>
    public static async Task<string> ReadAllTextAsync(this string file, bool exclusive = false)
    {
      if (File.Exists(file))
      {
        using (FileStream stream = File.Open(file, FileMode.Open, FileAccess.Read, exclusive ? FileShare.None : FileShare.ReadWrite))
        {
          return await stream.ReadAllTextAsync();
        }
      }
      else
      {
        throw new FileNotFoundException("JSON文件不存在：" + file);
      }
    }

    /// <summary>
    /// 将指定路径的文件（JSON格式）内容转换成键值对象
    /// </summary>
    /// <param name="file"></param>
    /// <param name="target">目标键值对象</param>
    /// <param name="exclusive">是否文件独占式访问</param>
    /// <returns></returns>
    public static IDictionary ReadJSON(this string file, IDictionary target = null, bool exclusive = false)
    {
      if (File.Exists(file))
      {
        if (exclusive)
        {
          using (FileStream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
          {
            target = stream.ReadAllText().ToDictionary().ToDictionary(target);
          }
        }
        else
        {
          target = File.ReadAllText(file).ToDictionary(target);
        }
      }
      else
      {
        throw new FileNotFoundException("JSON文件不存在：" + file);
      }
      return target;
    }

    /// <summary>
    /// 将指定路径的文件（JSON格式）内容转换成对象
    /// </summary>
    /// <param name="file"></param>
    /// <param name="exclusive"></param>
    /// <returns></returns>
    public static T ReadJSON<T>(this string file, bool exclusive = false)
    {
      object result = null;
      if (File.Exists(file))
      {
        if (exclusive)
        {
          using (FileStream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
          {
            result = stream.ReadAllText().Eval();
          }
        }
        else
        {
          result = File.ReadAllText(file).Eval();
        }
      }
      else
      {
        throw new FileNotFoundException("JSON文件不存在：" + file);
      }
      return (T)result;
    }

    /// <summary>
    /// 将指定对象序列化成JSON字符串并保存到指定文件
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="file"></param>
    public static void WriteJSON(this object obj, string file)
    {
      if (obj == null)
      {
        return;
      }
      FileInfo fileInfo = new FileInfo(file);
      if (!fileInfo.Directory.Exists)
      {
        fileInfo.Directory.Create();
      }
      File.WriteAllText(file, (obj is string) ? obj.ToString() : obj.ToJSON(), Encoding.UTF8);
    }

    /// <summary>
    /// 向指定文件写入指定对象的JSON序列化字符串
    /// </summary>
    /// <param name="file"></param>
    /// <param name="obj"></param>
    public static void WriteJSON(this string file, object obj) => obj.WriteJSON(file);

    /// <summary>
    /// 将指定路径文件的（JSON格式）内容转换层XMLDocument对象
    /// </summary>
    /// <param name="file"></param>
    /// <param name="tryCount">读取发生错误时重新读取的次数</param>
    /// <param name="interval">读取发生错误时重新读取的时间间隔（ms）</param>
    /// <returns></returns>
    public static XmlDocument ReadXML(this string file, int tryCount = 5, int interval = 1000)
    {
      XmlDocument doc = new XmlDocument();
      if (File.Exists(file))
      {
        int tryCounter = 1;
        try
        {
          doc.Load(file);
        }
        catch
        {
          while (tryCounter < tryCount)
          {
            Thread.Sleep(interval);
            doc.Load(file);
            tryCounter++;
          }
        }
      }
      else
      {
        throw new FileNotFoundException("指定的XML文件不存在！", file);
      }
      return doc;
    }

    /// <summary>
    /// 应用程序根路径
    /// </summary>
    public static string APP_ROOT_PATH = "";
    /// <summary>
    /// 返回指定相对路径对用的服务器端路径或应用程序运行时的路径
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string MapPath(this string exp, string separator = "/")
    {
      if (APP_ROOT_PATH.IsNotNullOrEmpty() && exp.StartsWith(APP_ROOT_PATH))
      {
        return exp;
      }
      exp = exp.Replace("~/", separator).AppendTrailingSlash(separator);
      return APP_ROOT_PATH.CombinePaths(separator, exp);
    }

    public static string MapWWWPath(this string exp, string separator = "/")
    {
      if (APP_ROOT_PATH.IsNotNullOrEmpty() && exp.StartsWith(APP_ROOT_PATH))
      {
        return exp;
      }
      exp = exp.Replace("~/", separator).AppendTrailingSlash(separator);
      return APP_ROOT_PATH.CombinePaths(separator, "wwwroot", exp);
    }

    public static Func<string, string> _unMapPath = null;
    /// <summary>
    /// 将指定的本地路径还原成当前服务器的根路径
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string UnMapPath(this string exp)
    {
      if (APP_ROOT_PATH.IsNotNullOrEmpty() && !exp.StartsWith(APP_ROOT_PATH))
      {
        return exp.Replace(APP_ROOT_PATH, "/").Replace('\\', '/');
      }
      return null;
    }

    /// <summary>
    /// 返回指定路径的文件信息对象
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    public static FileInfo FileInfo(this string file) => new FileInfo(file);

    /// <summary>
    /// 返回指定路径的文件夹信息对象
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static DirectoryInfo DirectoryInfo(this string path) => new DirectoryInfo(path);

    /// <summary>
    /// 循环指定文件夹下的所有文件
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="fun">返回true继续下一个，返回false跳出遍历</param>
    /// <param name="searchPattern"></param>
    /// <param name="searchOptions"></param>
    public static FileInfo[] EachAllFiles(this string exp, Func<FileInfo, bool> fun, string searchPattern = null, SearchOption searchOptions = SearchOption.AllDirectories)
    {
      if (Directory.Exists(exp))
      {
        FileInfo[] allFiles = exp.DirectoryInfo().GetFiles(searchPattern, searchOptions);
        if (allFiles != null)
        {
          allFiles.Map<FileInfo>(fun);
        }
        return allFiles;
      }
      return null;
    }


    /// <summary>
    /// 将JSON字符串转换成集合对象
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static IList ToList(this string exp) => exp.IsNullOrEmpty() ? null : exp.Eval() as IList;

    /// <summary>
    /// 将JSON字符串转换成键值对象
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this string exp)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      return JsonConvert.Import(exp) as IDictionary;
    }


    /// <summary>
    /// 将JSON字符串转换成键值对象并将值复制到目标键值对象中
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="target"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this string exp, IDictionary target = null)
    {
      if (string.IsNullOrEmpty(exp.Trim()))
      {
        return target;
      }
      IDictionary data = exp.ToDictionary();
      if (data != null && target != null)
      {
        data.CopyTo(target);
      }
      else
      {
        target = data;
      }
      return target;
    }

    /// <summary>
    /// 将指定集合转换成集合
    /// </summary>
    /// <param name="dataPrams"></param>
    /// <param name="parseNested">递归解析</param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this object[] dataPrams, bool parseNested = false)
    {
      int len = dataPrams.Length;
      IDictionary dict = new ListDictionary();
      for (int i = 0; i < len; i += 2)
      {
        object value = null;
        object key = dataPrams[i];
        if (i + 1 < len)
        {
          value = dataPrams[i + 1];
          if (parseNested)
          {
            if (value is object[])
            {
              value = (value as object[]).ToDictionary(parseNested);
            }
            else if (value is ArrayList)
            {
              ArrayList arrValue = (value as ArrayList);
              int valueLen = arrValue.Count;
              for (int index = 0; index < valueLen; index++)
              {
                value = arrValue[index];
                if (value is object[])
                {
                  value = (value as object[]).ToDictionary(parseNested);
                }
                arrValue[index] = value;
              }
              value = arrValue;
            }
          }
        }
        dict[key] = value;
      }
      return dict;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="parseNestedObjects"></param>
    /// <param name="dataPrams"></param>
    /// <returns></returns>
    public static IDictionary ParamsToDictionary(bool parseNestedObjects = false, params object[] dataPrams)
    {
      return dataPrams.ToDictionary(parseNestedObjects);
    }

    /// <summary>
    /// 将指定的字符串转换成字节数组，并且指定是否使用GZIP压缩，默认不压缩
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="useGZIP"></param>
    /// <returns></returns>
    public static byte[] ToByteArray(this string exp, bool useGZIP = false, Encoding enc = null)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      byte[] data = (enc != null ? enc : Encoding.UTF8).GetBytes(exp);
      if (!useGZIP)
      {
        return data;
      }
      MemoryStream ms = new MemoryStream();
      using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
      {
        zip.Write(data, 0, data.Length);
        zip.Close();
        ms.Seek(0, SeekOrigin.Begin);
        data = new byte[ms.Length];
        ms.Read(data, 0, (int)ms.Length);
        ms.Close();
        return data;
      }
    }

    /// <summary>
    /// 将指定的字符串转换成Base64编码的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string ToBase64(this string exp, bool useGZIP = false, Encoding enc = null)
    {
      return Convert.ToBase64String(exp.ToByteArray(useGZIP, enc));
    }

    /// <summary>
    /// 将Base64编码的字符串转换成正常的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string FromBase64(this string exp, bool useGZIP = false, Encoding enc = null)
    {
      return Convert.FromBase64String(exp).ToText(useGZIP, enc);
    }

    /// <summary>
    /// 将字符串转换成指定编码的Stream对象
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="useGZIP">是否使用GZIP压缩</param>
    /// <param name="enc">指定编码，默认UTF-8</param>
    /// <returns></returns>
    public static Stream ToStream(this string exp, bool useGZIP = false, Encoding enc = null)
    {
      var bytes = exp.ToByteArray(useGZIP, enc);
      return new MemoryStream(bytes);
    }

    /// <summary>
    /// 对指定字符串进行MD5加密,并返回Base64编码的字符串
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static string MD5Encrypt(this string source, bool base64 = true)
    {
      if (string.IsNullOrEmpty(source))
      {
        return null;
      }

      var md5 = new MD5CryptoServiceProvider();
      var byteData = source.ToByteArray();
      byteData = md5.ComputeHash(byteData);
      if (base64)
      {
        return Convert.ToBase64String(byteData);
      }
      var sb = new StringBuilder();
      foreach (byte b in byteData)
      {
        sb.Append(b.ToString("x2"));
      }
      return sb.ToString().ToUpper();
    }

    /// <summary>
    /// 对指定字符串进行SHA1加密,并返回Base64编码的字符串
    /// </summary>
    /// <param name="source"></param>
    /// <param name="base64"></param>
    /// <returns></returns>
    public static string SHA1Encrypt(this string source, bool base64 = true)
    {
      if (string.IsNullOrEmpty(source))
      {
        return null;
      }

      var md5 = new SHA1CryptoServiceProvider();
      var byteData = source.ToByteArray();
      byteData = md5.ComputeHash(byteData);
      if (base64)
      {
        return Convert.ToBase64String(byteData);
      }
      var sb = new StringBuilder();
      foreach (byte b in byteData)
      {
        sb.Append(b.ToString("x2"));
      }
      return sb.ToString().ToUpper();
    }

    /// <summary>
    /// 将指定字符串转换成指定类型的数组
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <param name="splitChar">分割符</param>
    /// <returns></returns>
    public static IList<T> ToArray<T>(this string exp, string[] splitChar)
    {
      string[] arr;
      List<T> resultArray = new List<T>();

      arr = exp.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);
      foreach (string str in arr)
      {
        resultArray.Add((T)Convert.ChangeType(str, typeof(T)));
      }
      return resultArray;
    }

    /// <summary>
    /// 压缩HTML
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string CompressAsHTML(this string exp)
    {
      string template;

      template = exp;
      if (!string.IsNullOrEmpty(template))
      {
        string[] arrPatterns =
              {
                ">\\s+(?=[^\\s])",
                "\\s+(?=<)",
                "\\s+{\\s+(?=[^\\s])",
                "\\s+}\\s+(?=[^\\s])",
                "\\s*;\\s+(?=[^\\s])",
                "\\s*\\[\\s+(?=[^\\s])",
                "\\s*\\]\\s+(?=[^\\s])",
                "\\s*\\(\\s+(?=[^\\s])",
                "\\s*\\)\\s+(?=[^\\s])",
                "\\s*,\\s+(?=[^\\s])",
                " +"
              };
        //<!DOCTYPE[^>]*>

        string[] arrReplaceValues = { ">", "", "{", "}", ";", "[", "]", "(", ")", ",", " " };
        Match matchDocTypeNode = Regex.Match(template, "<!DOCTYPE[^>]*>", RegexOptions.Multiline);
        string docTypeNodeValue = string.Empty;
        if (matchDocTypeNode != null)
        {
          docTypeNodeValue = matchDocTypeNode.Value;
          template = Regex.Replace(template, "<!DOCTYPE[^>]*>", "<!DOCTYPE>", RegexOptions.Multiline);
        }
        template = Regex.Replace(template, "<input.*__VIEWSTATE.*[^>]*/>", "", RegexOptions.Multiline);
        template = Regex.Replace(template, "<input type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\".*[^>]*/>", "", RegexOptions.Multiline);
        template = template.Replace("://", ":／／");
        template = Regex.Replace(template, "((\\/\\*[\\s\\S]*?\\*\\/)|(\\/\\/.*$))", "", RegexOptions.Multiline);
        template = template.Replace(":／／", "://");
        for (int i = 0; i < arrPatterns.Length; i++)
        {
          template = Regex.Replace(template, arrPatterns[i], arrReplaceValues[i]);
        }
        template = template.Replace("\n", "");
        template = template.Replace("\r", "");
        if (!string.IsNullOrEmpty(docTypeNodeValue))
        {
          template = template.Replace("<!DOCTYPE>", docTypeNodeValue);
        }
      }
      return template;
    }

    /// <summary>
    /// 压缩文本内容，将多个空格、换行压缩成一个空格
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="regexExp">用来查找空白字符串的正则表达式</param>
    /// <param name="replaceValue">用来替换空白的字符串</param>
    /// <returns></returns>
    public static string CompressAsText(this string exp, string regexExp = "\\s{2,}|\\n", string replaceValue = " ")
    {
      return Regex.Replace(exp, regexExp, replaceValue);
    }

    /// <summary>
    /// 检测字符串是否有Sql注入，并返回处理后的数据
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string ProcessSqlInject(this string exp)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      return exp.Replace("'", "''");
    }


    /// <summary>
    /// 注册指定路径（文件、文件夹）的监视
    /// </summary>
    /// <param name="path"></param>
    /// <param name="filter"></param>
    /// <param name="notifyFilters"></param>
    /// <param name="onChangedCallBack"></param>
    /// <returns></returns>
    public static IDictionary Watcher(this string path, Action<IDictionary, FileSystemEventArgs> onChangedCallBack, NotifyFilters notifyFilters = NotifyFilters.LastWrite, string filter = null)
    {
      string watcherPath = null;
      if (path.IsFileExists())
      {
        FileInfo file = path.FileInfo();
        watcherPath = file.DirectoryName;
        filter = filter.IsNullOrEmpty() ? file.Name : filter;
      }
      else if (path.IsPathExists())
      {
        watcherPath = path;
        filter = filter.IsNullOrEmpty() ? "*.*" : filter;
      }
      else
      {
        return null;
      }
      return FileSystemWatcherUtils.RegisterWatcher(watcherPath, filter, notifyFilters, onChangedCallBack);
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="compare"></param>
    /// <returns></returns>
    public static bool IsEquals(this String obj, String compare)
    {
      if (compare == null)
      {
        return false;
      }
      return obj.Equals(compare);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="separator"></param>
    /// <param name="ignoreEmpty"></param>
    /// <returns></returns>
    public static IList Split(this String exp, string separator, bool ignoreEmpty = true)
    {
      if (exp.IsNullOrEmpty())
      {
        return null;
      }
      return new List<string>
       (
         exp.Split(new string[] { separator }, ignoreEmpty ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None)
       );
    }

    /// <summary>
    /// 给指定的字符串路劲添加“\”或“/”结尾，如果已经存在了则不添加
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static string AppendTrailingSlash(this string path, string separator = "/")
    {
      return path.EndsWith(separator) ? path : path + separator;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="root"></param>
    /// <param name="separator"></param>
    /// <param name="paths"></param>
    /// <returns></returns>
    public static string CombinePaths(this string root, string separator = "/", params string[] paths)
    {
      IList result = new ArrayList();
      result.Add(root);
      result.AddList(paths);
      return result.Join(separator, (item, idx) =>
     {
       string path = item.ToString();
       if (path.StartsWith(separator))
       {
         path = path.Remove(0, separator.Length);
       }
       if (path.EndsWith(separator))
       {
         path = path.Remove(path.Length - separator.Length);
       }
       return path;
     });
    }

    /// <summary>
    /// 将指定的数据库类型名称转换成C#类型
    /// </summary>
    /// <param name="typeName"></param>
    /// <returns></returns>
    public static Type DBTypeToType(this string typeName, Type defaultType = null)
    {
      switch (typeName.ToLower())
      {
        case "bigint":
          return typeof(Int64);

        case "binary":
          return typeof(Object);

        case "bit":
          return typeof(Boolean);

        case "char":
        case "nchar":
        case "ntext":
        case "text":
        case "nvarchar":
        case "varchar":
          return typeof(String);

        case "date":
        case "datetime":
        case "smalldatetime":
          return typeof(DateTime);

        case "decimal":
        case "money":
        case "smallmoney":
          return typeof(Decimal);

        case "double":
          return typeof(Double);

        case "float":
        case "real":
          return typeof(Single);

        case "image":
        case "timestamp":
          return typeof(Byte[]);

        case "int":
          return typeof(Int32);

        case "smallint":
          return typeof(Int16);

        case "tinyint":
          return typeof(Byte);

        case "uniqueidentifier":
          return typeof(Guid);

        default:
          return defaultType != null ? defaultType : typeof(String);
      }
    }

    /// <summary>
    /// 将base64编码的urldata数据转换成二进制数组
    /// </summary>
    /// <param name="urlData"></param>
    /// <returns></returns>
    public static byte[] UrlDataToBytes(this string urlData)
    {
      if (urlData.IsNullOrEmpty())
      {
        return null;
      }
      var regex = new Regex("^data:.+;base64,");
      if (!regex.IsMatch(urlData))
      {
        throw new Exception("错误的UrlData数据格式！");
      }
      var match = regex.Match(urlData);
      urlData = urlData.Substring(match.Index + match.Length);
      return Convert.FromBase64String(urlData);
    }

    /// <summary>
    /// 将base64编码的urldata数据转保存为文件
    /// </summary>
    /// <param name="urlData"></param>
    /// <param name="filePath">服务器端的文件路径，可以是绝对路径(C:\1.data)，也可以是虚拟路径(~/1.data)</param>
    /// <returns></returns>
    public static bool UrlDataToFile(this string urlData, string filePath)
    {
      var buffer = urlData.UrlDataToBytes();

      if (buffer.IsNullOrEmpty())
      {
        return false;
      }
      File.WriteAllBytes(filePath.MapPath(), buffer);
      return true;
    }

    /// <summary>
    /// 移除指定开始位置和结束位置之间的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startIdx"></param>
    /// <param name="endIdx"></param>
    /// <returns></returns>
    public static string RemoveSubstring(this string exp, int startIdx, int endIdx)
    {
      if (startIdx >= 0 && endIdx > startIdx)
      {
        var startExp = string.Empty;
        var endExp = string.Empty;
        if (startIdx > 0)
        {
          startExp = exp.Substring(0, startIdx);
        }
        if (endIdx < exp.Length - 1)
        {
          endExp = exp.Substring(endIdx);
        }
        return $"{startExp}{endExp}";
      }
      return exp;
    }

    /// <summary>
    /// 移除指定开始字符串和结束字符串之间的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <returns></returns>
    public static string RemoveSubstring(this string exp, string startString, string endString)
    {
      var startIdx = exp.IndexOf(startString);
      if (startIdx >= 0)
      {
        var endIdx = exp.IndexOf(endString, startIdx);
        return exp.RemoveSubstring(startIdx, endIdx + endString.Length);
      }
      return exp;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startChar"></param>
    /// <param name="endChar"></param>
    /// <returns></returns>
    public static string RemoveSubstring(this string exp, char startChar, char endChar)
    {
      var startIdx = exp.IndexOf(startChar);
      if (startIdx >= 0)
      {
        var endIdx = exp.IndexOf(endChar, startIdx);
        return exp.RemoveSubstring(startIdx, endIdx + 1);
      }
      return exp;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startRegex"></param>
    /// <param name="endRegex"></param>
    /// <returns></returns>
    public static string RemoveSubstring(this string exp, Regex startRegex, Regex endRegex)
    {
      var startMatch = startRegex.Match(exp);
      var endMatch = endRegex.Match(exp);
      var startIdx = startMatch.Index;
      if (startIdx >= 0)
      {
        var endIdx = endMatch.Index;
        return exp.RemoveSubstring(startIdx, endIdx + endMatch.Length);
      }
      return exp;
    }

    /// <summary>
    /// 【提取】出指定开始字符和结束字符之间的字符串，result参数返回提取之后剩下的字符串，不包括【开始字符串】和【结束字符串】
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public static string PickSubstring(this string exp, string startString, string endString, out string result)
    {
      result = exp;
      var startIdx = exp.IndexOf(startString);
      if (startIdx >= 0)
      {
        var endIdx = exp.IndexOf(endString, startIdx);
        if (endIdx > startIdx)
        {
          var startExp = string.Empty;
          var endExp = string.Empty;
          startExp = exp.Substring(0, startIdx);
          endExp = exp.Substring(endIdx + endString.Length);
          result = $"{startExp}{endExp}";
          return exp.Substring(startIdx + startString.Length, endIdx - startIdx - startString.Length);
        }
      }
      return string.Empty;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <returns></returns>
    public static (string pick, string result) PickSubstring(this string exp, string startString, string endString)
    {
      var pick = exp.PickSubstring(startString, endString, out var result);
      return (pick, result);
    }

    /// <summary>
    /// 【提取】出指定开始字符和结束字符之间的字符串，result参数返回提取之后剩下的字符串，不包括【开始字符串】和【结束字符串】
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startChar"></param>
    /// <param name="endChar"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public static string PickSubstring(this string exp, char startChar, char endChar, out string result)
    {
      result = exp;
      var startIdx = exp.IndexOf(startChar);
      if (startIdx >= 0)
      {
        var endIdx = exp.IndexOf(endChar, startIdx);
        if (endIdx > startIdx)
        {
          var startExp = string.Empty;
          var endExp = string.Empty;
          startExp = exp.Substring(0, startIdx);
          endExp = exp.Substring(endIdx + 1);
          result = $"{startExp}{endExp}";
          return exp.Substring(startIdx + 1, endIdx - startIdx - 1);
        }
      }
      return string.Empty;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <returns></returns>
    public static (string pick, string result) PickSubstring(this string exp, char startChar, char endChar)
    {
      var pick = exp.PickSubstring(startChar, endChar, out var result);
      return (pick, result);
    }

    /// <summary>
    /// 【提取】出指定正则表达式匹配位置之间的字符串，result参数返回提取之后剩下的字符串，不包括【开始字符串】和【结束字符串】
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startRegex"></param>
    /// <param name="endRegex"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public static string PickSubstring(this string exp, Regex startRegex, Regex endRegex, out string result)
    {
      result = exp;
      var startMatch = startRegex.Match(exp);

      var startIdx = startMatch.Index;
      if (startIdx >= 0)
      {
        var endMatch = endRegex.Match(exp);
        var endIdx = endMatch.Index;
        if (endIdx > startIdx)
        {
          var startExp = string.Empty;
          var endExp = string.Empty;
          startExp = exp.Substring(0, startIdx);
          endExp = exp.Substring(endIdx + endMatch.Length);
          result = $"{startExp}{endExp}";
          return exp.Substring(startIdx + startMatch.Length, endIdx - startIdx - 1);
        }
      }
      return string.Empty;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <returns></returns>
    public static (string pick, string result) PickSubstring(this string exp, Regex startRegex, Regex endRegex)
    {
      var pick = exp.PickSubstring(startRegex, endRegex, out var result);
      return (pick, result);
    }

    /// <summary>
    /// 截取指定正则表达式匹配位置之间的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startRegex"></param>
    /// <param name="endRegex"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string MidSubstring(this string exp, Regex startRegex, Regex endRegex, string defaultVal = "")
    {
      var startMatch = startRegex.Match(exp);
      var endMatch = endRegex.Match(exp);
      var startIdx = startMatch.Index;
      var endIdx = endMatch.Index;
      if (startIdx < 0 || endIdx < 0 || endIdx <= startIdx)
      {
        return defaultVal;
      }
      return exp.Substring(startIdx + startMatch.Length, endIdx - startIdx - startMatch.Length);
    }

    /// <summary>
    /// 截取指定开始字符与结束字符之间的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startChar"></param>
    /// <param name="endChar"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string MidSubstring(this string exp, char startChar, char endChar, string defaultVal = "")
    {
      var startIdx = exp.IndexOf(startChar);
      var endIdx = exp.LastIndexOf(endChar);
      if (startIdx < 0 || endIdx < 0 || endIdx <= startIdx)
      {
        return defaultVal;
      }
      return exp.Substring(startIdx + 1, endIdx - startIdx - 1);
    }

    /// <summary>
    /// 截取指定开始字符串与结束字符串之间的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="startString"></param>
    /// <param name="endString"></param>
    /// <returns></returns>
    public static string MidSubstring(this string exp, string startString, string endString, string defaultVal = "")
    {
      var startIdx = exp.IndexOf(startString);
      var endIdx = exp.LastIndexOf(endString);
      if (startIdx < 0 || endIdx < 0 || endIdx <= startIdx)
      {
        return defaultVal;
      }
      return exp.Substring(startIdx + startString.Length, endIdx - startIdx - startString.Length);
    }

    /// <summary>
    /// 截取指定正则表达式匹配位置之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="searchRegex"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftSubstring(this string exp, Regex searchRegex, string defaultVal = "")
    {
      var match = searchRegex.Match(exp);
      if (match.Index < 0)
      {
        return defaultVal;
      }
      return exp.Substring(0, match.Index);
    }

    /// <summary>
    /// 截取指定字符串之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagString"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftSubstring(this string exp, string tagString, string defaultVal = "")
    {
      var idx = exp.IndexOf(tagString);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(0, idx);
    }

    /// <summary>
    /// 截取指定字符之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagChar"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftSubstring(this string exp, char tagChar, string defaultVal = "")
    {
      var idx = exp.IndexOf(tagChar);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(0, idx);
    }

    /// <summary>
    /// 截取指定正则表达式匹配位置之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="searchRegex"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftEndString(this string exp, Regex searchRegex, string defaultVal = "")
    {
      var match = searchRegex.Match(exp);
      if (match.Index < 0)
      {
        return defaultVal;
      }
      return exp.Substring(match.Index + match.Length);
    }

    /// <summary>
    /// 截取指定字符串之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagString"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftEndString(this string exp, string tagString, string defaultVal = "")
    {
      var idx = exp.IndexOf(tagString);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(idx + tagString.Length);
    }

    /// <summary>
    /// 截取指定字符之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagChar"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string LeftEndString(this string exp, char tagChar, string defaultVal = "")
    {
      var idx = exp.IndexOf(tagChar);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(idx + 1);
    }

    /// <summary>
    /// 从右侧查找指定正则表达式匹配位置之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="searchRegex"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightSubstring(this string exp, Regex searchRegex, string defaultVal = "")
    {
      var matches = searchRegex.Matches(exp);
      if (matches.Count == 0)
      {
        return defaultVal;
      }
      var lastMatch = matches.Last<Match>();
      return exp.Substring(0, lastMatch.Index);
    }

    /// <summary>
    /// 从右侧查找截取指定字符串之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagString"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightSubstring(this string exp, string tagString, string defaultVal = "")
    {
      var idx = exp.LastIndexOf(tagString);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(0, idx);
    }

    /// <summary>
    /// 从右侧查找截取指定字符串之前的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagString"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightSubstring(this string exp, char tagChar, string defaultVal = "")
    {
      var idx = exp.LastIndexOf(tagChar);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(0, idx);
    }


    /// <summary>
    /// 从右侧查找指定正则表达式匹配位置之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="searchRegex"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightEndString(this string exp, Regex searchRegex, string defaultVal = "")
    {
      var matches = searchRegex.Matches(exp);
      if (matches.Count == 0)
      {
        return defaultVal;
      }
      var lastMatch = matches.Last<Match>();
      return exp.Substring(lastMatch.Index + lastMatch.Length);
    }


    /// <summary>
    /// 从右侧查找截取指定字符串之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagString"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightEndString(this string exp, string tagString, string defaultVal = "")
    {
      var idx = exp.LastIndexOf(tagString);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(idx + tagString.Length);
    }

    /// <summary>
    /// 从右侧查找截取指定字符之后的字符串
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="tagChar"></param>
    /// <param name="defaultVal"></param>
    /// <returns></returns>
    public static string RightEndString(this string exp, char tagChar, string defaultVal = "")
    {
      var idx = exp.LastIndexOf(tagChar);
      if (idx == -1)
      {
        return defaultVal;
      }
      return exp.Substring(idx + 1);
    }


    /// <summary>
    /// DES加密
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="key">加密秘钥</param>
    /// <returns></returns>
    public static string DESEncrypt(this string exp, string key, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
    {
      if (key.Length != 16)
      {
        key = key.MD5Encrypt(false);
      }
      var keyBytes = key.Substring(0, 8).ToByteArray();
      var keyIV = key.Substring(key.Length - 9, 8).ToByteArray();
      var inputByteArray = Encoding.UTF8.GetBytes(exp);
      using (var provider = new DESCryptoServiceProvider() { Mode = mode, Padding = padding })
      {
        using (var mStream = new MemoryStream())
        {
          using (var cStream = new CryptoStream(mStream, provider.CreateEncryptor(keyBytes, keyIV), CryptoStreamMode.Write))
          {
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Convert.ToBase64String(mStream.ToArray());
          }
        }
      }
    }

    /// <summary>
    /// 进行两次DES加密
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string DESEncrypt2(this string exp, string key, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
    {
      key = key.MD5Encrypt(false);
      var key1 = key.Substring(0, 16);
      var key2 = key.Substring(16, 16);
      return exp.DESEncrypt(key1, mode, padding).DESEncrypt(key2, mode, padding);
    }

    /// <summary>
    /// DES解密
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string DESDecrypt(this string exp, string key, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
    {
      if (key.Length != 16)
      {
        key = key.MD5Encrypt(false);
      }
      var keyBytes = key.Substring(0, 8).ToByteArray();
      var keyIV = key.Substring(key.Length - 9, 8).ToByteArray();
      var inputByteArray = Convert.FromBase64String(exp);
      using (var provider = new DESCryptoServiceProvider() { Mode = mode, Padding = padding })
      {
        using (var mStream = new MemoryStream())
        {
          using (var cStream = new CryptoStream(mStream, provider.CreateDecryptor(keyBytes, keyIV), CryptoStreamMode.Write))
          {
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(mStream.ToArray());
          }
        }
      }
    }


    /// <summary>
    /// 进行两次DES解密
    /// </summary>
    /// <param name="exp"></param>
    /// <param name="key"></param>
    /// <param name="mode"></param>
    /// <param name="padding"></param>
    /// <returns></returns>
    public static string DESDecrypt2(this string exp, string key, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
    {
      key = key.MD5Encrypt(false);
      var key1 = key.Substring(0, 16);
      var key2 = key.Substring(16, 16);
      return exp.DESDecrypt(key2, mode, padding).DESDecrypt(key1, mode, padding);
    }

    /// <summary>
    /// SHA1加密
    /// </summary>
    /// <param name="exp"></param>
    /// <returns></returns>
    public static string SHA1Encrypt(this string exp)
    {
      var bytes = Encoding.Default.GetBytes(exp);
      var iSHA = new SHA1CryptoServiceProvider();
      bytes = iSHA.ComputeHash(bytes);
      var sb = new StringBuilder();
      foreach (var iByte in bytes)
      {
        sb.AppendFormat("{0:x2}", iByte);
      }
      return sb.ToString().ToLower();
    }
    #endregion 字符串扩展
  }
}
